package net.minecraft.client.gui;

import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.awt.Toolkit;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.stream.GuiTwitchUserMode;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.entity.RenderItem;
import net.minecraft.entity.EntityList;
import net.minecraft.event.ClickEvent;
import net.minecraft.event.HoverEvent;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.JsonToNBT;
import net.minecraft.nbt.NBTException;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.stats.Achievement;
import net.minecraft.stats.StatBase;
import net.minecraft.stats.StatList;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IChatComponent;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import tv.twitch.chat.ChatUserInfo;

public abstract class GuiScreen extends Gui implements GuiYesNoCallback
{
    private static final Logger field_175287_a = LogManager.getLogger();
    private static final Set field_175284_f = Sets.newHashSet(new String[] {"http", "https"});
    private static final Splitter field_175285_g = Splitter.on('\n');

    /** Reference to the Minecraft object. */
    protected Minecraft mc;

    /**
     * Holds a instance of RenderItem, used to draw the achievement icons on screen (is based on ItemStack)
     */
    protected RenderItem itemRender;

    /** The width of the screen object. */
    public int width;

    /** The height of the screen object. */
    public int height;

    /** A list of all the buttons in this container. */
    protected List buttonList = Lists.newArrayList();

    /** A list of all the labels in this container. */
    protected List labelList = Lists.newArrayList();
    public boolean allowUserInput;

    /** The FontRenderer used by GuiScreen */
    protected FontRenderer fontRendererObj;

    /** The button that was just pressed. */
    private GuiButton selectedButton;
    protected int eventButton;
    private long lastMouseEvent;

    /**
     * Incremented when the game is in touchscreen mode and the screen is tapped, decremented if the screen isn't
     * tapped. Does not appear to be used.
     */
    private int touchValue;
    private URI field_175286_t;
    private static final String __OBFID = "CL_00000710";

    /**
     * Draws the screen and all the components in it. Args : mouseX, mouseY, renderPartialTicks
     */
    public void drawScreen(int mouseX, int mouseY, float partialTicks)
    {
        int var4;

        for (var4 = 0; var4 < this.buttonList.size(); ++var4)
        {
            ((GuiButton)this.buttonList.get(var4)).drawButton(this.mc, mouseX, mouseY);
        }

        for (var4 = 0; var4 < this.labelList.size(); ++var4)
        {
            ((GuiLabel)this.labelList.get(var4)).drawLabel(this.mc, mouseX, mouseY);
        }
    }

    /**
     * Fired when a key is typed (except F11 who toggle full screen). This is the equivalent of
     * KeyListener.keyTyped(KeyEvent e). Args : character (character on the key), keyCode (lwjgl Keyboard key code)
     */
    protected void keyTyped(char typedChar, int keyCode) throws IOException
    {
        if (keyCode == 1)
        {
            this.mc.displayGuiScreen((GuiScreen)null);

            if (this.mc.currentScreen == null)
            {
                this.mc.setIngameFocus();
            }
        }
    }

    /**
     * Returns a string stored in the system clipboard.
     */
    public static String getClipboardString()
    {
        try
        {
            Transferable var0 = Toolkit.getDefaultToolkit().getSystemClipboard().getContents((Object)null);

            if (var0 != null && var0.isDataFlavorSupported(DataFlavor.stringFlavor))
            {
                return (String)var0.getTransferData(DataFlavor.stringFlavor);
            }
        }
        catch (Exception var1)
        {
            ;
        }

        return "";
    }

    /**
     * Stores the given string in the system clipboard
     */
    public static void setClipboardString(String copyText)
    {
        if (!StringUtils.isEmpty(copyText))
        {
            try
            {
                StringSelection var1 = new StringSelection(copyText);
                Toolkit.getDefaultToolkit().getSystemClipboard().setContents(var1, (ClipboardOwner)null);
            }
            catch (Exception var2)
            {
                ;
            }
        }
    }

    protected void renderToolTip(ItemStack itemIn, int x, int y)
    {
        List var4 = itemIn.getTooltip(this.mc.thePlayer, this.mc.gameSettings.advancedItemTooltips);

        for (int var5 = 0; var5 < var4.size(); ++var5)
        {
            if (var5 == 0)
            {
                var4.set(var5, itemIn.getRarity().rarityColor + (String)var4.get(var5));
            }
            else
            {
                var4.set(var5, EnumChatFormatting.GRAY + (String)var4.get(var5));
            }
        }

        this.drawHoveringText(var4, x, y);
    }

    /**
     * Draws the text when mouse is over creative inventory tab. Params: current creative tab to be checked, current
     * mouse x position, current mouse y position.
     */
    protected void drawCreativeTabHoveringText(String tabName, int mouseX, int mouseY)
    {
        this.drawHoveringText(Arrays.asList(new String[] {tabName}), mouseX, mouseY);
    }

    protected void drawHoveringText(List textLines, int x, int y)
    {
        if (!textLines.isEmpty())
        {
            GlStateManager.disableRescaleNormal();
            RenderHelper.disableStandardItemLighting();
            GlStateManager.disableLighting();
            GlStateManager.disableDepth();
            int var4 = 0;
            Iterator var5 = textLines.iterator();

            while (var5.hasNext())
            {
                String var6 = (String)var5.next();
                int var7 = this.fontRendererObj.getStringWidth(var6);

                if (var7 > var4)
                {
                    var4 = var7;
                }
            }

            int var14 = x + 12;
            int var15 = y - 12;
            int var8 = 8;

            if (textLines.size() > 1)
            {
                var8 += 2 + (textLines.size() - 1) * 10;
            }

            if (var14 + var4 > this.width)
            {
                var14 -= 28 + var4;
            }

            if (var15 + var8 + 6 > this.height)
            {
                var15 = this.height - var8 - 6;
            }

            this.zLevel = 300.0F;
            this.itemRender.zLevel = 300.0F;
            int var9 = -267386864;
            this.drawGradientRect(var14 - 3, var15 - 4, var14 + var4 + 3, var15 - 3, var9, var9);
            this.drawGradientRect(var14 - 3, var15 + var8 + 3, var14 + var4 + 3, var15 + var8 + 4, var9, var9);
            this.drawGradientRect(var14 - 3, var15 - 3, var14 + var4 + 3, var15 + var8 + 3, var9, var9);
            this.drawGradientRect(var14 - 4, var15 - 3, var14 - 3, var15 + var8 + 3, var9, var9);
            this.drawGradientRect(var14 + var4 + 3, var15 - 3, var14 + var4 + 4, var15 + var8 + 3, var9, var9);
            int var10 = 1347420415;
            int var11 = (var10 & 16711422) >> 1 | var10 & -16777216;
            this.drawGradientRect(var14 - 3, var15 - 3 + 1, var14 - 3 + 1, var15 + var8 + 3 - 1, var10, var11);
            this.drawGradientRect(var14 + var4 + 2, var15 - 3 + 1, var14 + var4 + 3, var15 + var8 + 3 - 1, var10, var11);
            this.drawGradientRect(var14 - 3, var15 - 3, var14 + var4 + 3, var15 - 3 + 1, var10, var10);
            this.drawGradientRect(var14 - 3, var15 + var8 + 2, var14 + var4 + 3, var15 + var8 + 3, var11, var11);

            for (int var12 = 0; var12 < textLines.size(); ++var12)
            {
                String var13 = (String)textLines.get(var12);
                this.fontRendererObj.func_175063_a(var13, (float)var14, (float)var15, -1);

                if (var12 == 0)
                {
                    var15 += 2;
                }

                var15 += 10;
            }

            this.zLevel = 0.0F;
            this.itemRender.zLevel = 0.0F;
            GlStateManager.enableLighting();
            GlStateManager.enableDepth();
            RenderHelper.enableStandardItemLighting();
            GlStateManager.enableRescaleNormal();
        }
    }

    protected void func_175272_a(IChatComponent p_175272_1_, int p_175272_2_, int p_175272_3_)
    {
        if (p_175272_1_ != null && p_175272_1_.getChatStyle().getChatHoverEvent() != null)
        {
            HoverEvent var4 = p_175272_1_.getChatStyle().getChatHoverEvent();

            if (var4.getAction() == HoverEvent.Action.SHOW_ITEM)
            {
                ItemStack var5 = null;

                try
                {
                    NBTTagCompound var6 = JsonToNBT.func_180713_a(var4.getValue().getUnformattedText());

                    if (var6 instanceof NBTTagCompound)
                    {
                        var5 = ItemStack.loadItemStackFromNBT((NBTTagCompound)var6);
                    }
                }
                catch (NBTException var11)
                {
                    ;
                }

                if (var5 != null)
                {
                    this.renderToolTip(var5, p_175272_2_, p_175272_3_);
                }
                else
                {
                    this.drawCreativeTabHoveringText(EnumChatFormatting.RED + "Invalid Item!", p_175272_2_, p_175272_3_);
                }
            }
            else
            {
                String var8;

                if (var4.getAction() == HoverEvent.Action.SHOW_ENTITY)
                {
                    if (this.mc.gameSettings.advancedItemTooltips)
                    {
                        try
                        {
                            NBTTagCompound var12 = JsonToNBT.func_180713_a(var4.getValue().getUnformattedText());

                            if (var12 instanceof NBTTagCompound)
                            {
                                ArrayList var14 = Lists.newArrayList();
                                NBTTagCompound var7 = (NBTTagCompound)var12;
                                var14.add(var7.getString("name"));

                                if (var7.hasKey("type", 8))
                                {
                                    var8 = var7.getString("type");
                                    var14.add("Type: " + var8 + " (" + EntityList.func_180122_a(var8) + ")");
                                }

                                var14.add(var7.getString("id"));
                                this.drawHoveringText(var14, p_175272_2_, p_175272_3_);
                            }
                            else
                            {
                                this.drawCreativeTabHoveringText(EnumChatFormatting.RED + "Invalid Entity!", p_175272_2_, p_175272_3_);
                            }
                        }
                        catch (NBTException var10)
                        {
                            this.drawCreativeTabHoveringText(EnumChatFormatting.RED + "Invalid Entity!", p_175272_2_, p_175272_3_);
                        }
                    }
                }
                else if (var4.getAction() == HoverEvent.Action.SHOW_TEXT)
                {
                    this.drawHoveringText(field_175285_g.splitToList(var4.getValue().getFormattedText()), p_175272_2_, p_175272_3_);
                }
                else if (var4.getAction() == HoverEvent.Action.SHOW_ACHIEVEMENT)
                {
                    StatBase var13 = StatList.getOneShotStat(var4.getValue().getUnformattedText());

                    if (var13 != null)
                    {
                        IChatComponent var15 = var13.getStatName();
                        ChatComponentTranslation var16 = new ChatComponentTranslation("stats.tooltip.type." + (var13.isAchievement() ? "achievement" : "statistic"), new Object[0]);
                        var16.getChatStyle().setItalic(Boolean.valueOf(true));
                        var8 = var13 instanceof Achievement ? ((Achievement)var13).getDescription() : null;
                        ArrayList var9 = Lists.newArrayList(new String[] {var15.getFormattedText(), var16.getFormattedText()});

                        if (var8 != null)
                        {
                            var9.addAll(this.fontRendererObj.listFormattedStringToWidth(var8, 150));
                        }

                        this.drawHoveringText(var9, p_175272_2_, p_175272_3_);
                    }
                    else
                    {
                        this.drawCreativeTabHoveringText(EnumChatFormatting.RED + "Invalid statistic/achievement!", p_175272_2_, p_175272_3_);
                    }
                }
            }

            GlStateManager.disableLighting();
        }
    }

    protected void func_175274_a(String p_175274_1_, boolean p_175274_2_) {}

    protected boolean func_175276_a(IChatComponent p_175276_1_)
    {
        if (p_175276_1_ == null)
        {
            return false;
        }
        else
        {
            ClickEvent var2 = p_175276_1_.getChatStyle().getChatClickEvent();

            if (isShiftKeyDown())
            {
                if (p_175276_1_.getChatStyle().getInsertion() != null)
                {
                    this.func_175274_a(p_175276_1_.getChatStyle().getInsertion(), false);
                }
            }
            else if (var2 != null)
            {
                URI var3;

                if (var2.getAction() == ClickEvent.Action.OPEN_URL)
                {
                    if (!this.mc.gameSettings.chatLinks)
                    {
                        return false;
                    }

                    try
                    {
                        var3 = new URI(var2.getValue());

                        if (!field_175284_f.contains(var3.getScheme().toLowerCase()))
                        {
                            throw new URISyntaxException(var2.getValue(), "Unsupported protocol: " + var3.getScheme().toLowerCase());
                        }

                        if (this.mc.gameSettings.chatLinksPrompt)
                        {
                            this.field_175286_t = var3;
                            this.mc.displayGuiScreen(new GuiConfirmOpenLink(this, var2.getValue(), 31102009, false));
                        }
                        else
                        {
                            this.func_175282_a(var3);
                        }
                    }
                    catch (URISyntaxException var4)
                    {
                        field_175287_a.error("Can\'t open url for " + var2, var4);
                    }
                }
                else if (var2.getAction() == ClickEvent.Action.OPEN_FILE)
                {
                    var3 = (new File(var2.getValue())).toURI();
                    this.func_175282_a(var3);
                }
                else if (var2.getAction() == ClickEvent.Action.SUGGEST_COMMAND)
                {
                    this.func_175274_a(var2.getValue(), true);
                }
                else if (var2.getAction() == ClickEvent.Action.RUN_COMMAND)
                {
                    this.func_175281_b(var2.getValue(), false);
                }
                else if (var2.getAction() == ClickEvent.Action.TWITCH_USER_INFO)
                {
                    ChatUserInfo var5 = this.mc.getTwitchStream().func_152926_a(var2.getValue());

                    if (var5 != null)
                    {
                        this.mc.displayGuiScreen(new GuiTwitchUserMode(this.mc.getTwitchStream(), var5));
                    }
                    else
                    {
                        field_175287_a.error("Tried to handle twitch user but couldn\'t find them!");
                    }
                }
                else
                {
                    field_175287_a.error("Don\'t know how to handle " + var2);
                }

                return true;
            }

            return false;
        }
    }

    public void func_175275_f(String p_175275_1_)
    {
        this.func_175281_b(p_175275_1_, true);
    }

    public void func_175281_b(String p_175281_1_, boolean p_175281_2_)
    {
        if (p_175281_2_)
        {
            this.mc.ingameGUI.getChatGUI().addToSentMessages(p_175281_1_);
        }

        this.mc.thePlayer.sendChatMessage(p_175281_1_);
    }

    /**
     * Called when the mouse is clicked. Args : mouseX, mouseY, clickedButton
     */
    protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException
    {
        if (mouseButton == 0)
        {
            for (int var4 = 0; var4 < this.buttonList.size(); ++var4)
            {
                GuiButton var5 = (GuiButton)this.buttonList.get(var4);

                if (var5.mousePressed(this.mc, mouseX, mouseY))
                {
                    this.selectedButton = var5;
                    var5.playPressSound(this.mc.getSoundHandler());
                    this.actionPerformed(var5);
                }
            }
        }
    }

    /**
     * Called when a mouse button is released.  Args : mouseX, mouseY, releaseButton
     */
    protected void mouseReleased(int mouseX, int mouseY, int state)
    {
        if (this.selectedButton != null && state == 0)
        {
            this.selectedButton.mouseReleased(mouseX, mouseY);
            this.selectedButton = null;
        }
    }

    /**
     * Called when a mouse button is pressed and the mouse is moved around. Parameters are : mouseX, mouseY,
     * lastButtonClicked & timeSinceMouseClick.
     */
    protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) {}

    protected void actionPerformed(GuiButton button) throws IOException {}

    /**
     * Causes the screen to lay out its subcomponents again. This is the equivalent of the Java call
     * Container.validate()
     */
    public void setWorldAndResolution(Minecraft mc, int width, int height)
    {
        this.mc = mc;
        this.itemRender = mc.getRenderItem();
        this.fontRendererObj = mc.fontRendererObj;
        this.width = width;
        this.height = height;
        this.buttonList.clear();
        this.initGui();
    }

    /**
     * Adds the buttons (and other controls) to the screen in question.
     */
    public void initGui() {}

    /**
     * Delegates mouse and keyboard input.
     */
    public void handleInput() throws IOException
    {
        if (Mouse.isCreated())
        {
            while (Mouse.next())
            {
                this.handleMouseInput();
            }
        }

        if (Keyboard.isCreated())
        {
            while (Keyboard.next())
            {
                this.handleKeyboardInput();
            }
        }
    }

    /**
     * Handles mouse input.
     */
    public void handleMouseInput() throws IOException
    {
        int var1 = Mouse.getEventX() * this.width / this.mc.displayWidth;
        int var2 = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
        int var3 = Mouse.getEventButton();

        if (Mouse.getEventButtonState())
        {
            if (this.mc.gameSettings.touchscreen && this.touchValue++ > 0)
            {
                return;
            }

            this.eventButton = var3;
            this.lastMouseEvent = Minecraft.getSystemTime();
            this.mouseClicked(var1, var2, this.eventButton);
        }
        else if (var3 != -1)
        {
            if (this.mc.gameSettings.touchscreen && --this.touchValue > 0)
            {
                return;
            }

            this.eventButton = -1;
            this.mouseReleased(var1, var2, var3);
        }
        else if (this.eventButton != -1 && this.lastMouseEvent > 0L)
        {
            long var4 = Minecraft.getSystemTime() - this.lastMouseEvent;
            this.mouseClickMove(var1, var2, this.eventButton, var4);
        }
    }

    /**
     * Handles keyboard input.
     */
    public void handleKeyboardInput() throws IOException
    {
        if (Keyboard.getEventKeyState())
        {
            this.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey());
        }

        this.mc.dispatchKeypresses();
    }

    /**
     * Called from the main game loop to update the screen.
     */
    public void updateScreen() {}

    /**
     * Called when the screen is unloaded. Used to disable keyboard repeat events
     */
    public void onGuiClosed() {}

    /**
     * Draws either a gradient over the background screen (when it exists) or a flat gradient over background.png
     */
    public void drawDefaultBackground()
    {
        this.drawWorldBackground(0);
    }

    public void drawWorldBackground(int tint)
    {
        if (this.mc.theWorld != null)
        {
            this.drawGradientRect(0, 0, this.width, this.height, -1072689136, -804253680);
        }
        else
        {
            this.drawBackground(tint);
        }
    }

    /**
     * Draws the background (i is always 0 as of 1.2.2)
     */
    public void drawBackground(int tint)
    {
        GlStateManager.disableLighting();
        GlStateManager.disableFog();
        Tessellator var2 = Tessellator.getInstance();
        WorldRenderer var3 = var2.getWorldRenderer();
        this.mc.getTextureManager().bindTexture(optionsBackground);
        GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
        float var4 = 32.0F;
        var3.startDrawingQuads();
        var3.func_178991_c(4210752);
        var3.addVertexWithUV(0.0D, (double)this.height, 0.0D, 0.0D, (double)((float)this.height / var4 + (float)tint));
        var3.addVertexWithUV((double)this.width, (double)this.height, 0.0D, (double)((float)this.width / var4), (double)((float)this.height / var4 + (float)tint));
        var3.addVertexWithUV((double)this.width, 0.0D, 0.0D, (double)((float)this.width / var4), (double)tint);
        var3.addVertexWithUV(0.0D, 0.0D, 0.0D, 0.0D, (double)tint);
        var2.draw();
    }

    /**
     * Returns true if this GUI should pause the game when it is displayed in single-player
     */
    public boolean doesGuiPauseGame()
    {
        return true;
    }

    public void confirmClicked(boolean result, int id)
    {
        if (id == 31102009)
        {
            if (result)
            {
                this.func_175282_a(this.field_175286_t);
            }

            this.field_175286_t = null;
            this.mc.displayGuiScreen(this);
        }
    }

    private void func_175282_a(URI p_175282_1_)
    {
        try
        {
            Class var2 = Class.forName("java.awt.Desktop");
            Object var3 = var2.getMethod("getDesktop", new Class[0]).invoke((Object)null, new Object[0]);
            var2.getMethod("browse", new Class[] {URI.class}).invoke(var3, new Object[] {p_175282_1_});
        }
        catch (Throwable var4)
        {
            field_175287_a.error("Couldn\'t open link", var4);
        }
    }

    /**
     * Returns true if either windows ctrl key is down or if either mac meta key is down
     */
    public static boolean isCtrlKeyDown()
    {
        return Minecraft.isRunningOnMac ? Keyboard.isKeyDown(219) || Keyboard.isKeyDown(220) : Keyboard.isKeyDown(29) || Keyboard.isKeyDown(157);
    }

    /**
     * Returns true if either shift key is down
     */
    public static boolean isShiftKeyDown()
    {
        return Keyboard.isKeyDown(42) || Keyboard.isKeyDown(54);
    }

    public static boolean func_175283_s()
    {
        return Keyboard.isKeyDown(56) || Keyboard.isKeyDown(184);
    }

    public static boolean func_175277_d(int p_175277_0_)
    {
        return p_175277_0_ == 45 && isCtrlKeyDown();
    }

    public static boolean func_175279_e(int p_175279_0_)
    {
        return p_175279_0_ == 47 && isCtrlKeyDown();
    }

    public static boolean func_175280_f(int p_175280_0_)
    {
        return p_175280_0_ == 46 && isCtrlKeyDown();
    }

    public static boolean func_175278_g(int p_175278_0_)
    {
        return p_175278_0_ == 30 && isCtrlKeyDown();
    }

    public void func_175273_b(Minecraft mcIn, int p_175273_2_, int p_175273_3_)
    {
        this.setWorldAndResolution(mcIn, p_175273_2_, p_175273_3_);
    }
}
